package com.hx.controller;

import com.hx.entity.BaseTemplateVO;
import com.hx.utils.Word2PdfUtil;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.documents.BookmarksNavigator;
import com.spire.doc.documents.ImageType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

@Slf4j
@RestController
@Api(value = "文档转换")
@RequestMapping("/convert")
public class DocumentConvertController {

    /**
     * MultipartFile 默认尺寸不能超过1MB  如果需要传大文件 需要在配置文件里设置
     */
    @ApiOperation(value = "word转pdf")
    @PostMapping("/wordToPdf")
    public ResponseEntity wordToPdf(@RequestParam("srcPath") String srcPath,
                                    @RequestParam("outPath") String outPath) throws IOException {

        try {
            Word2PdfUtil.wordConvertPdfFile(srcPath, outPath);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ResponseEntity.ok().build();
    }

    @ApiOperation(value = "根据word模板创建文档")
    @PostMapping("/creat/word/baseTemplate")
    public ResponseEntity baseTemplate(@RequestBody @Validated @ApiParam(value = "替换参数") BaseTemplateVO baseTemplateVO) throws IOException {
        String srcPath = baseTemplateVO.getSrcPath();
        String outPath = baseTemplateVO.getOutPath();
        Map<String, Object> map = baseTemplateVO.getMap();
        searchAndReplace(srcPath, outPath, map);
        if (baseTemplateVO.getIsOutPdf()) {
            String pdfPath = outPath.replace(".docx", ".pdf");
            replaceBookMark(outPath);
            wordToPdf(outPath, pdfPath);
            log.info("word转pdf成功！");
        }
        return ResponseEntity.ok("根据word模板创建文档成功！");
    }

    /**
     * 将word模板中的文字进行替换
     */
    public static void searchAndReplace(String srcPath, String destPath, Map<String, Object> map) {
        FileOutputStream outStream = null;
        try {
            // 替换的的关键字存放到Set集合中
            Set<String> set = map.keySet();
            // 读取模板文档
            XWPFDocument document = new XWPFDocument(new FileInputStream(srcPath));
            replaceParagraph(map, document, set);
            replaceTable(map, document);
//            输出替换后的Word文档
            outStream = new FileOutputStream(destPath);
            document.write(outStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }


    /**
     * 替换书签名称
     */
    public static void replaceBookMark(String outPutFilePath) {
        log.info("正在修改生成的word文档书签！");
        //加载包含书签的Word文档
        Document doc = new Document();
        doc.loadFromFile(outPutFilePath);
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(doc);
        bookmarksNavigator.moveToBookmark("start");
        //用文本内容替换原有书签位置的文本，新替换的内容与原文格式一致
        bookmarksNavigator.replaceBookmarkContent("qq", true);
        bookmarksNavigator.moveToBookmark("ww");
        bookmarksNavigator.replaceBookmarkContent("bbb", true);
        bookmarksNavigator.moveToBookmark("end");
        bookmarksNavigator.replaceBookmarkContent("bbb", true);
        bookmarksNavigator.moveToBookmark("zongshi");
        bookmarksNavigator.replaceBookmarkContent("马斯克", true);

        //保存文档
        doc.saveToFile(outPutFilePath, FileFormat.Docx_2013);
        doc.dispose();
    }

    /*public void replaceBookMark2(Map<String, Object> map, XWPFDocument document) {
        String inputFilePath = "C:\\Users\\蓝色思维\\Desktop/测试模板.docx";
        String outputFilePath = "C:\\Users\\蓝色思维\\Desktop/output.docx";

        //加载包含书签的Word文档
        Document doc = new Document();
        doc.loadFromFile(inputFilePath);

        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(doc);
        bookmarksNavigator.moveToBookmark("start");

        //用文本内容替换原有书签位置的文本，新替换的内容与原文格式一致
        bookmarksNavigator.replaceBookmarkContent("aaa", true);

        bookmarksNavigator.moveToBookmark("end");
        bookmarksNavigator.replaceBookmarkContent("bbb", true);
        //保存文档
        doc.saveToFile(outputFilePath, FileFormat.Docx_2013);
        doc.dispose();
    }*/

    /**
     * 替换段落中的指定文字
     */
    private static void replaceParagraph(Map<String, Object> map, XWPFDocument document, Set<String> set) {

        // 读取文档中的段落，回车符为一个段落。
        // 同一个段落里面会被“:”等符号隔开为多个对象
        Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
        while (itPara.hasNext()) {
            // 获取文档中当前的段落文字信息
            XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
            List<XWPFRun> run = paragraph.getRuns();
            // 遍历段落文字对象
            for (int i = 0; i < run.size(); i++) {
                // 获取段落对象
                if (run.get(i) == null) {    //段落为空跳过
                    continue;
                }
                String sectionItem = run.get(i).getText(run.get(i).getTextPosition());    //段落内容
                // 遍历自定义表单关键字，替换Word文档中的内容
                Iterator<String> iterator = set.iterator();
                while (iterator.hasNext()) {
                    // 当前关键字
                    String key = iterator.next();
                    // 替换内容
                    if (sectionItem == null) {
                        continue;
                    }
                    sectionItem = sectionItem.replace(key, String.valueOf(map.get(key)));
                }
                run.get(i).setText(sectionItem, 0);
            }
        }
    }

    /**
     * 替换表格中的指定文字
     */
    private static void replaceTable(Map<String, Object> map, XWPFDocument document) {

        //获取文档中所有的表格，每个表格是一个元素
        Iterator<XWPFTable> itTable = document.getTablesIterator();
        while (itTable.hasNext()) {
            XWPFTable table = (XWPFTable) itTable.next();   //获取表格内容
            int count = table.getNumberOfRows();    //表格的行数
            //遍历表格行的对象
            List<Integer> rowIds = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                XWPFTableRow row = table.getRow(i);    //表格每行的内容
                List<XWPFTableCell> cells = row.getTableCells();   //每个单元格的内容
                //遍历表格的每行单元格对象
                for (int j = 0; j < cells.size(); j++) {
                    XWPFTableCell cell = cells.get(j);    //获取每个单元格的内容
                    String text = cell.getText();
                    if ("总师审核".equals(text) && !(Boolean) map.get("isAudit")) {
                        log.info("第{}行从左到右第{}个单元格的内容 {} 待删除！", i + 1, j + 1, text);
                        rowIds.add(i);
                    }
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();      //获取单元格里所有的段落
                    for (XWPFParagraph paragraph : paragraphs) {
                        //获取段落的内容
                        List<XWPFRun> run = paragraph.getRuns();
                        // 遍历段落文字对象
                        for (int o = 0; o < run.size(); o++) {
                            // 获取段落对象
                            if (run.get(o) == null || run.get(o).equals("")) {
                                continue;
                            }
                            String sectionItem = run.get(o).getText(run.get(o).getTextPosition());    //获取段落内容
                            if (sectionItem == null || sectionItem.equals("")) {    //段落为空跳过
                                continue;
                            }
                            //遍历自定义表单关键字，替换Word文档中表格单元格的内容
                            for (String key : map.keySet()) {
                                // 替换内容
                                sectionItem = sectionItem.replace(key, String.valueOf(map.get(key)));
                                run.get(o).setText(sectionItem, 0);
                            }
                        }
                    }
                }
            }
            for (Integer rowId : rowIds) {
                table.removeRow(rowId);
            }
        }
    }


}